package com.wangzhen.codebase.transfermoney.lock11;

/**
 * lock1版本的升级版，主要优化点在于将transfer方法内部的while (!allocater.apply(this, target))
 * 改进为等待通知机制，当有线程拿不到锁的时候会调用wait方法进入等待，当有线程执行完毕之后会调用notifyAll
 * 唤醒等待的线程
 */
public class Account {

    private static final Allocater allocater = new Allocater();

    private Integer balance;

    private Account(Integer balance) {
        this.balance = balance;
    }

    @Override
    public String toString() {
        return "Account{" +
                "balance=" + balance +
                '}';
    }

    public void transfer(Account target, Integer account) {
        // 没有申请到锁就一直等着
        allocater.apply(this, target);
        try {
            if (this.balance >= account) {
                this.balance -= account;
                target.balance += account;
            } else {
                System.out.println("余额不足！！！");
            }
        } finally {
            // 释放锁
            allocater.free(this, target);
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Account a1 = new Account(100);
        Account a2 = new Account(100);
        Account a3 = new Account(100);

        Thread t1 = new Thread(()-> {a1.transfer(a2,100);
            System.out.printf("thread name=%s, finish time=%d \n", Thread.currentThread().getName(), System.currentTimeMillis());});
        Thread t2 = new Thread(()-> {a2.transfer(a3,100);
            System.out.printf("thread name=%s, finish time=%d \n", Thread.currentThread().getName(), System.currentTimeMillis());});


        t1.start();t2.start();
        t1.join();t2.join();

        System.out.println(a1);
        System.out.println(a2);
        System.out.println(a3);

    }
}
